#include "../interface/T_gl_Asset.h"

#include "../rtCommon/xobj_string.h"
#include "../interface/T_Buffer_GL.h"

#pragma warning(disable: 4996)
#pragma warning(disable: 4267)

C_gl_Asset::C_gl_Asset(void)
{
	m_nPrimitive = 0;
	m_nVertex = 0;
}

C_gl_Asset::~C_gl_Asset(void)
{
	Release();
}

void C_gl_Asset::Create(int nVertexCount, int nFaceCount, int nFlag, I_api_Device * pDevice)
{
	if (nFlag & e_Asset_Data_Pos) {
		if (m_pPos == NULL) m_pPos = new T_Buffer_GL<T_pos>();
		m_pPos->Create(nVertexCount, pDevice);
	}

	if (nFlag & e_Asset_Data_Idx) {
		if (m_pPosIdx == NULL) m_pPosIdx = new T_Buffer_GL<T_idx>();
		m_pPosIdx->Create(nFaceCount, pDevice);
	}

	if (nFlag & e_Asset_Data_Nml) {
		if (m_pNml == NULL) m_pNml = new T_Buffer_GL<T_nml>();
		m_pNml->Create(nVertexCount, pDevice);
	}

	if (nFlag & e_Asset_Data_Tnt) {
		if (m_pTnt == NULL) m_pTnt = new T_Buffer_GL<T_tnt>();
		m_pTnt->Create(nVertexCount, pDevice);
	}

	if (nFlag & e_Asset_Data_Bnt) {
		if (m_pBnt == NULL) m_pBnt = new T_Buffer_GL<T_bnt>();
		m_pBnt->Create(nVertexCount, pDevice);
	}

	if (nFlag & e_Asset_Data_Clr) {
		if (m_pClr == NULL) m_pClr = new T_Buffer_GL<T_clr>();
		m_pClr->Create(nVertexCount, pDevice);
	}

	if (nFlag & e_Asset_Data_UV) {
		if (m_pUV == NULL) m_pUV = new T_Buffer_GL<T_uv>();
		m_pUV->Create(nVertexCount, pDevice);
	}

	if (nFlag & e_Asset_Data_Tree) if (m_pTree == NULL) m_pTree = new C_gl_SpatialTree();
}

void C_gl_Asset::Create(int nVertexCount, int nFaceCount, int nFlag, I_Asset * pShared)
{
	if (nFlag & e_Asset_Data_Pos) {
		if (m_pPos == NULL) m_pPos = new T_Buffer_GL<T_pos>();
		m_pPos->Create(nVertexCount, pShared->m_pPos);
	}

	if (nFlag & e_Asset_Data_Idx) {
		if (m_pPosIdx == NULL) m_pPosIdx = new T_Buffer_GL<T_idx>();
		m_pPosIdx->Create(nFaceCount, pShared->m_pPosIdx);
	}

	if (nFlag & e_Asset_Data_Nml) {
		if (m_pNml == NULL) m_pNml = new T_Buffer_GL<T_nml>();
		m_pNml->Create(nVertexCount, pShared->m_pNml);
	}

	if (nFlag & e_Asset_Data_Tnt) {
		if (m_pTnt == NULL) m_pTnt = new T_Buffer_GL<T_tnt>();
		m_pTnt->Create(nVertexCount, pShared->m_pTnt);
	}

	if (nFlag & e_Asset_Data_Bnt) {
		if (m_pBnt == NULL) m_pBnt = new T_Buffer_GL<T_bnt>();
		m_pBnt->Create(nVertexCount, pShared->m_pBnt);
	}

	if (nFlag & e_Asset_Data_Clr) {
		if (m_pClr == NULL) m_pClr = new T_Buffer_GL<T_clr>();
		m_pClr->Create(nVertexCount, pShared->m_pClr);
	}

	if (nFlag & e_Asset_Data_UV) {
		if (m_pUV == NULL) m_pUV = new T_Buffer_GL<T_uv>();
		m_pUV->Create(nVertexCount, pShared->m_pUV);
	}

	if (nFlag & e_Asset_Data_Tree) if (m_pTree == NULL) m_pTree = new C_gl_SpatialTree(); 
}

bool C_gl_Asset::Deserialize(char * pFileName, I_api_Device * pDevice)
{
	char aString[XOBJ_MAX_STRING_LENGTH];

	int iv = 0, ivn = 0, ivc = 0, ivt = 0, ifv = 0, ift = 0, ifc = 0;
	int numV = 0, numF = 0, numTV = 0, numCV = 0;    

  if (pFileName == NULL ) return false;

  FILE *pFile = fopen(pFileName, "r");
  if (pFile == NULL) return false;

  while (!feof(pFile))
  {
		memset(aString, 0, XOBJ_MAX_STRING_LENGTH);
		fscanf(pFile, "%s", aString);

    // -------------------------------------------------------------------- Node Counter
    if (strcmp(aString, STRING_NODE_COUNTER) == 0)
    {     
      iv = ivn = ivc = ivt = ifv = ift = ifc = 0;
			numV = numF = numTV = numCV = 0;
      continue;
    }
		// -------------------------------------------------------------------- Array sizes
		if (strcmp(aString, STRING_FACE_COUNT) == 0)
		{			
			fscanf(pFile, "%d", &numF);

			m_nPrimitive = numF;
			numF *= 3;

			Create(0, numF, e_Asset_Data_Idx, pDevice);
			continue;
		}

		if (strcmp(aString, STRING_VERTEX_COUNT) == 0)
		{
			fscanf(pFile, "%d", &numV);
			
			m_nVertex = numV;

			Create(numV, 0, e_Asset_Data_Pos | e_Asset_Data_Nml, pDevice);
			continue;
		}

		if (strcmp(aString, STRING_TEXTURE_COUNT) == 0)
		{
			fscanf(pFile, "%d", &numTV);		

			//Create(numV, 0, e_Asset_Data_UV, pDevice);
			continue;
		}

		if (strcmp(aString, STRING_COLOR_COUNT) == 0)
		{
			fscanf(pFile, "%d", &numCV);

			//Create(numV, 0, e_Asset_Data_Clr, pDevice);
			continue;
		}

		// -------------------------------------------------------------------- Vertex Attributes
		if (strcmp(aString, STRING_V_MODEL ) == 0)
		{
			T_pos v;
			float3 f3v;

			fscanf(pFile, "%f%f%f", &f3v.x, &f3v.y, &f3v.z);
			
			if (iv == 0)
				m_Box = S_Box(f3v);
			else{
				m_Box.min(f3v);
				m_Box.max(f3v);
			}

			v.x = f3v.x;
			v.y = f3v.y;
			v.z = f3v.z;
			((T_pos*)m_pPos->hPtr())[iv++] = v;
			continue;
		}

		if (strcmp(aString, STRING_VN) == 0)
		{
			T_nml n;
			float3 f3n;

			fscanf(pFile, "%f%f%f", &f3n.x, &f3n.y, &f3n.z);
			n.x = f3n.x;
			n.y = f3n.y;
			n.z = f3n.z;
			((T_nml*)m_pNml->hPtr())[ivn++] = n;
			continue;
		}

		if (strcmp(aString, STRING_VC) == 0)
		{
			T_clr c;
			float3 f3c;
			fscanf(pFile, "%f%f%f", &f3c.x, &f3c.y, &f3c.z);

			c.x = f3c.x;
			c.y = f3c.y;
			c.z = f3c.z;
			
			//((T_clr*)m_pClr->hPtr())[ivc++] = c;
			continue;
		}

		if (strcmp(aString, STRING_VT) == 0)
		{
			T_uv uv;
			float3 f3uv;

			fscanf(pFile, "%f%f%f", &f3uv.x, &f3uv.y, &f3uv.z);

			uv.x = f3uv.x;
			uv.y = f3uv.y;

			//((T_uv*)m_pUV->hPtr())[ivt++] = uv;
			continue;
		}

		// -------------------------------------------------------------------- Faces
		if (strcmp(aString, STRING_FV_XOBJ) == 0)
		{
			int3 vf = {0, 0, 0};

			fscanf(pFile, "%d%d%d", &vf.x, &vf.y, &vf.z);
			
			((T_idx*)m_pPosIdx->hPtr())[ifv++] = vf.x;
			((T_idx*)m_pPosIdx->hPtr())[ifv++] = vf.y;
			((T_idx*)m_pPosIdx->hPtr())[ifv++] = vf.z;
			continue;
		}
  }
	return true;
}

bool C_gl_Asset::Deserialize(char * pFileName, I_Asset *pShared)
{
	if (pShared == NULL) return false;

	char aString[XOBJ_MAX_STRING_LENGTH];

	int iv = 0, ivn = 0, ivc = 0, ivt = 0, ifv = 0, ift = 0, ifc = 0;
	int numV = 0, numF = 0, numTV = 0, numCV = 0;    

	if (pFileName == NULL ) return false;

	FILE *pFile = fopen(pFileName, "r");
	if (pFile == NULL) return false;

	while (!feof(pFile))
	{
		memset(aString, 0, XOBJ_MAX_STRING_LENGTH);
		fscanf(pFile, "%s", aString);

		// -------------------------------------------------------------------- Node Counter
		if (strcmp(aString, STRING_NODE_COUNTER) == 0)
		{     
			iv = ivn = ivc = ivt = ifv = ift = ifc = 0;
			numV = numF = numTV = numCV = 0;
			continue;
		}
		// -------------------------------------------------------------------- Array sizes
		if (strcmp(aString, STRING_FACE_COUNT) == 0)
		{			
			fscanf(pFile, "%d", &numF);

			m_nPrimitive = numF;
			numF *= 3;
			
			Create(0, numF, e_Asset_Data_Idx, pShared);
			continue;
		}

		if (strcmp(aString, STRING_VERTEX_COUNT) == 0)
		{
			fscanf(pFile, "%d", &numV);

			m_nVertex = numV;

			Create(numV, 0, e_Asset_Data_Pos | e_Asset_Data_Nml, pShared);
			continue;
		}

		if (strcmp(aString, STRING_TEXTURE_COUNT) == 0)
		{
			fscanf(pFile, "%d", &numTV);		

			//Create(numV, 0, e_Asset_Data_UV, pShared);
			continue;
		}

		if (strcmp(aString, STRING_COLOR_COUNT) == 0)
		{
			fscanf(pFile, "%d", &numCV);

			//Create(numV, 0, e_Asset_Data_Clr, pShared);
			continue;
		}

		// -------------------------------------------------------------------- Vertex Attributes
		if (strcmp(aString, STRING_V_MODEL ) == 0)
		{
			T_pos v;
			float3 f3v;

			fscanf(pFile, "%f%f%f", &f3v.x, &f3v.y, &f3v.z);

			v.x = f3v.x;
			v.y = f3v.y;
			v.z = f3v.z;

			if (iv == 0)
				m_Box = S_Box(f3v);
			else
			{
				m_Box.min(f3v);
				m_Box.max(f3v);
			}

			((T_pos*)m_pPos->hPtr())[iv++] = v;
			continue;
		}

		if (strcmp(aString, STRING_VN) == 0)
		{
			T_nml n;
			float3 f3n;

			fscanf(pFile, "%f%f%f", &f3n.x, &f3n.y, &f3n.z);
			n.x = f3n.x;
			n.y = f3n.y;
			n.z = f3n.z;
			((T_nml*)m_pNml->hPtr())[ivn++] = n;
			continue;
		}

		if (strcmp(aString, STRING_VC) == 0)
		{
			T_clr c;
			float3 f3c;
			fscanf(pFile, "%f%f%f", &f3c.x, &f3c.y, &f3c.z);

			c.x = f3c.x;
			c.y = f3c.y;
			c.z = f3c.z;

			//((T_clr*)m_pClr->hPtr())[ivc++] = c;
			continue;
		}

		if (strcmp(aString, STRING_VT) == 0)
		{
			T_uv uv;
			float3 f3uv;

			fscanf(pFile, "%f%f%f", &f3uv.x, &f3uv.y, &f3uv.z);

			uv.x = f3uv.x;
			uv.y = f3uv.y;

			//((T_uv*)m_pUV->hPtr())[ivt++] = uv;
			continue;
		}

		// -------------------------------------------------------------------- Faces
		if (strcmp(aString, STRING_FV_XOBJ) == 0)
		{
			int3 vf = {0, 0, 0};

			fscanf(pFile, "%d%d%d", &vf.x, &vf.y, &vf.z);

			((T_idx*)m_pPosIdx->hPtr())[ifv++] = vf.x;
			((T_idx*)m_pPosIdx->hPtr())[ifv++] = vf.y;
			((T_idx*)m_pPosIdx->hPtr())[ifv++] = vf.z;
			continue;
		}
	}

	return true;
}

bool C_gl_Asset::Serialize(char * pFileName)
{
	return true;
}

void	C_gl_Asset::Build(int nType)
{
	m_pTree->PrimitiveAABB();

	if (nType == e_SpatialTree_Bvh){
		m_pTree->BVHTree_p0();
		m_pTree->BVHTree_p1();
	}
	
	if (nType == e_SpatialTree_Kd){
		m_pTree->KdTree_p0();
		m_pTree->KdTree_p0();
	}
}